Deduplicazione delle Risorse in React Suspense: Prevenire Richieste Duplicate | MLOG | MLOG

Ora, UserResource controlla se una risorsa esiste già nella cache. Se esiste, viene restituita la risorsa in cache. Altrimenti, viene avviata una nuova richiesta e la promise risultante viene memorizzata nella cache. Ciò garantisce che venga effettuata una sola richiesta per ogni userId univoco.

2. Usare una Libreria di Caching Dedicata (es. `lru-cache`)

Per scenari di caching più complessi, considera l'utilizzo di una libreria di caching dedicata come lru-cache o simili. Queste librerie forniscono funzionalità come l'eliminazione dalla cache basata su Least Recently Used (LRU) o altre politiche, che possono essere cruciali per la gestione dell'utilizzo della memoria, specialmente quando si ha a che fare con un gran numero di risorse.

Per prima cosa, installa la libreria:

            
npm install lru-cache

            

Quindi, integrala nel tuo UserResource:

            
import React, { Suspense } from 'react';
import LRUCache from 'lru-cache';

const fetchUser = (userId) => {
  console.log(`Recupero utente con ID: ${userId}`); // Simula una richiesta di rete
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: userId, name: `User ${userId}`, email: `user${userId}@example.com` });
    }, 1000); // Simula la latenza di rete
  });
};

const cache = new LRUCache({
  max: 100, // Numero massimo di elementi nella cache
  ttl: 60000, // Tempo di vita in millisecondi (1 minuto)
});

const UserResource = (userId) => {
  if (!cache.has(userId)) {
    let promise = null;
    let status = 'pending'; // in attesa, successo, errore
    let result;

    const suspender = fetchUser(userId).then(
      (r) => {
        status = 'success';
        result = r;
        cache.set(userId, {
          read() {
            return result;
          },
        });
      },
      (e) => {
        status = 'error';
        result = e;
        cache.set(userId, {
          read() {
            throw result;
          },
        });
      }
    );

    cache.set(userId, {
        read() {
            if (status === 'pending') {
                throw suspender;
            } else if (status === 'error') {
                throw result;
            }
            return result;
        }
    });
  }

  return cache.get(userId);
};


const UserProfile = ({ userId }) => {
  const user = UserResource(userId).read();
  return (
    

Profilo Utente

ID: {user.id}

Nome: {user.name}

Email: {user.email}

); }; const UserDetails = ({ userId }) => { const user = UserResource(userId).read(); return (

Dettagli Utente

ID: {user.id}

Nome: {user.name}

); }; const App = () => { return ( Caricamento...
}> ); }; export default App;

Questo approccio fornisce un maggiore controllo sulla dimensione e sulla politica di scadenza della cache.

3. Coalescenza delle Richieste con Librerie come `axios-extensions`

Librerie come axios-extensions offrono funzionalità più avanzate come la coalescenza delle richieste. La coalescenza delle richieste combina più richieste identiche in un'unica richiesta, ottimizzando ulteriormente l'uso della rete. Ciò è particolarmente utile in scenari in cui le richieste vengono avviate molto vicine tra loro nel tempo.

Per prima cosa, installa la libreria:

            
npm install axios axios-extensions

            

Quindi, configura Axios con l'adattatore cache fornito da axios-extensions.

Esempio di utilizzo di `axios-extensions` e creazione di una risorsa:

            
import React, { Suspense } from 'react';
import axios from 'axios';
import { cacheAdapterEnhancer, throttleAdapterEnhancer } from 'axios-extensions';

const instance = axios.create({
  baseURL: 'https://api.example.com', // Sostituisci con il tuo endpoint API
  adapter: cacheAdapterEnhancer(axios.defaults.adapter, { enabledByDefault: true }),
});

const fetchUser = async (userId) => {
  console.log(`Recupero utente con ID: ${userId}`); // Simula una richiesta di rete
  const response = await instance.get(`/users/${userId}`);
  return response.data;
};


const UserResource = (userId) => {
    let promise = null;
    let status = 'pending'; // in attesa, successo, errore
    let result;

    const suspender = fetchUser(userId).then(
        (r) => {
            status = 'success';
            result = r;
        },
        (e) => {
            status = 'error';
            result = e;
        }
    );

    return {
        read() {
            if (status === 'pending') {
                throw suspender;
            } else if (status === 'error') {
                throw result;
            }
            return result;
        },
    };
};


const UserProfile = ({ userId }) => {
  const user = UserResource(userId).read();
  return (
    

Profilo Utente

ID: {user.id}

Nome: {user.name}

Email: {user.email}

); }; const UserDetails = ({ userId }) => { const user = UserResource(userId).read(); return (

Dettagli Utente

ID: {user.id}

Nome: {user.name}

); }; const App = () => { return ( Caricamento...
}> ); }; export default App;

Questo configura Axios per utilizzare un adattatore di cache, mettendo automaticamente in cache le risposte in base alla configurazione della richiesta. La funzione cacheAdapterEnhancer fornisce opzioni per configurare la cache, come l'impostazione di una dimensione massima della cache o di un tempo di scadenza. throttleAdapterEnhancer può anche essere utilizzato per limitare il numero di richieste effettuate al server entro un certo periodo di tempo, ottimizzando ulteriormente le prestazioni.

Best Practice per la Deduplicazione delle Risorse

Considerazioni Globali per il Recupero e la Deduplicazione dei Dati

Quando si progettano strategie di recupero dati per un pubblico globale, entrano in gioco diversi fattori:

Ad esempio, un sito web di prenotazione viaggi che si rivolge a un pubblico globale potrebbe utilizzare una CDN per servire i dati sulla disponibilità di voli e hotel da server situati in diverse regioni. Il sito web utilizzerebbe anche un'API di conversione di valuta per visualizzare i prezzi nella valuta locale dell'utente e fornirebbe opzioni per filtrare i risultati di ricerca in base alle preferenze linguistiche.

Conclusione

La deduplicazione delle risorse è una tecnica di ottimizzazione essenziale per le applicazioni React che utilizzano Suspense. Prevenendo le richieste duplicate di dati, è possibile migliorare significativamente le prestazioni, ridurre il carico del server e migliorare l'esperienza dell'utente. Sia che si scelga di implementare una semplice cache di promise o di sfruttare librerie più avanzate come lru-cache o axios-extensions, la chiave è comprendere i principi sottostanti e scegliere la soluzione che meglio si adatta alle proprie esigenze specifiche. Ricordare di considerare fattori globali come CDN, localizzazione e accessibilità durante la progettazione delle strategie di recupero dati per un pubblico eterogeneo. Implementando queste best practice, è possibile creare applicazioni React più veloci, efficienti e facili da usare.